﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using EstateNuke.Data.Properties;

namespace EstateNuke.Data
{
    public partial class Company
    {
        #region Fileds & Properties

        /// <summary>
        /// </summary>
        public string DisplayName
        {
            get
            {
                return string.Format("{0}{1}", Name, IsDeleted ? " (已删除)" : "");
            }
        }

        /// <summary>
        /// </summary>
        public IList<Department> Departments
        {
            get
            {
                return InternalDepartments.Where(department => department.IsDeleted == false).ToList();
            }
        }

        /// <summary>
        /// </summary>
        public IList<District> Districts
        {
            get
            {
                return InternalDistricts.Where(district => district.IsDeleted == false).ToList();
            }
        }

        /// <summary>
        /// </summary>
        public IList<Project> Projects
        {
            get
            {
                return InternalProjects.Where(project => project.IsDeleted == false).ToList();
            }
        }

        /// <summary>
        /// </summary>
        public IList<User> Users
        {
            get
            {
                return InternalUsers.Where(user => user.IsDeleted == false).ToList();
            }
        }

        #endregion

        #region Add & Remove Department

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public Department AddDepartment(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var department = new Department
                                 {
                                     RowId = Guid.NewGuid(),
                                     CreatedDate = DateTime.Now,
                                 };
            InternalDepartments.Add(department);
            department.IsDeleted = false;
            department.ModifiedDate = DateTime.Now;
            department.ModifiedByUser = modifiedUser;
            return department;
        }

        /// <summary>
        /// </summary>
        /// <param name = "name"></param>
        /// <param name = "modifiedUser"></param>
        /// <returns></returns>
        public Department AddDepartment(string name, User modifiedUser)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalDepartments.Any(item => item.IsDeleted == false && item.Name == name))
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.DuplicatedDepartment, name));
            }
            var department = InternalDepartments.FirstOrDefault(item => item.IsDeleted && item.Name == name);
            if (department == null)
            {
                department = new Department
                                 {
                                     RowId = Guid.NewGuid(),
                                     CreatedDate = DateTime.Now,
                                 };
                InternalDepartments.Add(department);
            }
            department.IsDeleted = false;
            department.ModifiedDate = DateTime.Now;
            department.ModifiedByUser = modifiedUser;
            department.Name = name;
            return department;
        }

        /// <summary>
        /// </summary>
        /// <param name = "department"></param>
        /// <param name = "modifiedUser"></param>
        public void RemoveDepartment(Department department, User modifiedUser)
        {
            if (department == null)
            {
                throw new ArgumentNullException("department");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalDepartments.Contains(department))
            {
                department.Delete(modifiedUser);
            }
        }

        #endregion

        #region Add & Remove District

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public District AddDistrict(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var district = new District
                               {
                                   RowId = Guid.NewGuid(),
                                   CreatedDate = DateTime.Now,
                               };
            InternalDistricts.Add(district);
            district.IsDeleted = false;
            district.ModifiedDate = DateTime.Now;
            district.ModifiedByUser = modifiedUser;
            return district;
        }

        /// <summary>
        /// </summary>
        /// <param name = "name"></param>
        /// <param name = "modifiedUser"></param>
        /// <returns></returns>
        public District AddDistrict(string name, User modifiedUser)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalDistricts.Any(item => item.IsDeleted == false && item.Name == name))
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.DuplicatedDistrict, name));
            }
            var district = InternalDistricts.FirstOrDefault(item => item.IsDeleted && item.Name == name);
            if (district == null)
            {
                district = new District
                               {
                                   RowId = Guid.NewGuid(),
                                   CreatedDate = DateTime.Now,
                               };
                InternalDistricts.Add(district);
            }
            district.IsDeleted = false;
            district.ModifiedDate = DateTime.Now;
            district.ModifiedByUser = modifiedUser;
            district.Name = name;
            return district;
        }

        /// <summary>
        /// </summary>
        /// <param name = "district"></param>
        /// <param name = "modifiedUser"></param>
        public void RemoveDistrict(District district, User modifiedUser)
        {
            if (district == null)
            {
                throw new ArgumentNullException("district");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalDistricts.Contains(district))
            {
                district.Delete(modifiedUser);
            }
        }

        #endregion

        #region Add & Remove Project

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public Project AddProject(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var project = new Project
                              {
                                  RowId = Guid.NewGuid(),
                                  CreatedDate = DateTime.Now,
                              };
            InternalProjects.Add(project);
            project.IsDeleted = false;
            project.ModifiedDate = DateTime.Now;
            project.ModifiedByUser = modifiedUser;
            project.ProjectStateId = 1;
            return project;
        }

        /// <summary>
        /// </summary>
        /// <param name = "name"></param>
        /// <param name = "modifiedUser"></param>
        /// <returns></returns>
        public Project AddProject(string name, User modifiedUser)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalProjects.Any(item => item.IsDeleted == false && item.Name == name))
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.DuplicatedProject, name));
            }
            var project = InternalProjects.FirstOrDefault(item => item.IsDeleted && item.Name == name);
            if (project == null)
            {
                project = new Project
                              {
                                  RowId = Guid.NewGuid(),
                                  CreatedDate = DateTime.Now,
                              };
                InternalProjects.Add(project);
            }
            project.IsDeleted = false;
            project.ModifiedDate = DateTime.Now;
            project.ModifiedByUser = modifiedUser;
            project.Name = name;
            project.Code = name.GetFirstPinYin();
            project.ProjectStateId = 1;
            return project;
        }

        /// <summary>
        /// </summary>
        /// <param name = "project"></param>
        /// <param name = "modifiedUser"></param>
        public void RemoveProject(Project project, User modifiedUser)
        {
            if (project == null)
            {
                throw new ArgumentNullException("project");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalProjects.Contains(project))
            {
                project.Delete(modifiedUser);
            }
        }

        #endregion

        #region Add & Remove User

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public User AddUser(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var user = new User
                           {
                               RowId = Guid.NewGuid(),
                               CreatedDate = DateTime.Now,
                           };
            InternalUsers.Add(user);
            user.IsDeleted = false;
            user.ModifiedDate = DateTime.Now;
            user.ModifiedByUser = modifiedUser;
            user.IsApproved = true;
            user.IsLockedOut = false;
            user.FailedPasswordAnswerAttemptCount = 0;
            user.FailedPasswordAttemptCount = 0;
            return user;
        }

        /// <summary>
        /// </summary>
        /// <param name = "userName"></param>
        /// <param name = "modifiedUser"></param>
        /// <returns></returns>
        public User AddUser(string userName, User modifiedUser)
        {
            if (string.IsNullOrEmpty(userName))
            {
                throw new ArgumentNullException("userName");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalUsers.Any(p => p.IsDeleted == false && p.UserName == userName))
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.DuplicatedUser, userName));
            }
            var user = InternalUsers.FirstOrDefault(item => item.IsDeleted && item.UserName == userName);
            if (user == null)
            {
                user = new User
                           {
                               RowId = Guid.NewGuid(),
                               CreatedDate = DateTime.Now,
                           };
                InternalUsers.Add(user);
            }
            user.IsDeleted = false;
            user.ModifiedDate = DateTime.Now;
            user.ModifiedByUser = modifiedUser;
            user.UserName = userName;
            user.Name = userName;
            user.IsApproved = true;
            user.IsLockedOut = false;
            user.FailedPasswordAnswerAttemptCount = 0;
            user.FailedPasswordAttemptCount = 0;
            return user;
        }

        /// <summary>
        /// </summary>
        /// <param name = "user"></param>
        /// <param name = "modifiedUser"></param>
        public void RemoveUser(User user, User modifiedUser)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalUsers.Contains(user))
            {
                user.Delete(modifiedUser);
            }
        }

        #endregion

        #region Ensure

        /// <summary>
        /// </summary>
        public void Ensure()
        {
            if (string.IsNullOrEmpty(Name))
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NotNullAllowed, RowId, "Company", "Name"));
            }
            Name = Name.Length > 64 ? Name.Substring(0, 64) : Name;
            Description = string.IsNullOrEmpty(Description) ? null : Description.Length > 512 ? Description.Substring(0, 512) : Description;
        }

        #endregion

        #region Delete

        /// <summary>
        /// </summary>
        public void Delete(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            IsDeleted = true;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
            ((List<Department>) Departments).ForEach(department => department.Delete(modifiedUser));
            ((List<District>) Districts).ForEach(district => district.Delete(modifiedUser));
            ((List<Project>) Projects).ForEach(project => project.Delete(modifiedUser));
            ((List<User>) Users).ForEach(user => user.Delete(modifiedUser));
        }

        /// <summary>
        /// </summary>
        public void CancelDelete(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            IsDeleted = false;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
        }

        #endregion
    }

    public class CompanyEnum
    {
        #region Fields & Properties

        private readonly EstateNukeCore _context;

        private Company _default;

        /// <summary>
        /// </summary>
        public Company Default
        {
            get
            {
                return _default ?? (_default = _context.Companies.FirstOrDefault(company => company.Id == 1));
            }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// </summary>
        /// <param name = "context"></param>
        public CompanyEnum(EstateNukeCore context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            _context = context;
        }

        #endregion
    }
}